package cn.learn.service.impl;

import cn.learn.dao.OperationElasticsearchDocDao;
import cn.learn.domain.ElasticsearchQuery;
import cn.learn.service.IHandlerElasticSearchService;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * es的操作实现类
 *
 * @author huangyezhan
 * @version 1.0
 * @date 2020年06月30日9:17
 */
@Service
public class HandlerElasticSearchServiceImpl implements IHandlerElasticSearchService {

    @Autowired
    private OperationElasticsearchDocDao operationElasticsearchDoc;

    @Override
    public boolean createIndexMapping(String indexName, String mapping) throws IOException {
        return operationElasticsearchDoc.createIndexMapping(indexName, mapping);
    }

    @Override
    public boolean deleteIndex(String index) throws IOException {
        return operationElasticsearchDoc.deleteIndex(index);
    }

    @Override
    public Map<String, Object> queryTop10(ElasticsearchQuery query) throws IOException {
        SearchHits hits = operationElasticsearchDoc.query(query);
        return this.conversionObject(hits);
    }


    @Override
    public Map<String, Object> geoBoundingBox(ElasticsearchQuery query, String topLeft, String bottomRight) throws IOException {
        SearchHits hits = operationElasticsearchDoc.geoBoundingBox(query, topLeft, bottomRight);
        return this.conversionObject(hits);
    }

    @Override
    public Map<String, Object> geoPolygon(ElasticsearchQuery query, String[] points) throws IOException {
        List<GeoPoint> geoPoints = this.pointsArrayConvertList(points);
        SearchHits     hits      = operationElasticsearchDoc.geoPolygon(query, geoPoints);
        return this.conversionObject(hits);
    }


    @Override
    public void bulkAsync(String index, List<Map<String, String>> list) throws IOException, InterruptedException {
        if (list != null && list.size() > 0) {
            operationElasticsearchDoc.bulk(list, index);
        }
    }

    @Override
    public  Map<String, Object> officialDocument(ElasticsearchQuery query) throws IOException {
        SearchHits hits = operationElasticsearchDoc.officialDocument(query);
        return this.conversionDocs(hits);
    }



    /**
     * 坐标点数组转集合
     *
     * @param points 坐标点数组(维度、经度)
     * @return 返回集合
     */
    private List<GeoPoint> pointsArrayConvertList(String[] points) {
        List<GeoPoint> geoPoints = null;
        if (points != null && points.length > 0) {
            geoPoints = new ArrayList<>();
            for (String point : points) {
                String[] split = point.split(",");
                geoPoints.add(new GeoPoint(Double.parseDouble(split[1]), Double.parseDouble(split[0])));
            }
        }
        return geoPoints;
    }


    /**
     * 转换对象，把elasticsearch返回的结果对象，转换成指定对象
     */
    private Map<String, Object> conversionObject(SearchHits searchHits) {
        SearchHit[]         hits = searchHits.getHits();
        Map<String, Object> map  = null;
        if (hits.length > 0) {
            map = new HashMap<>();
            List<Map<String, Object>> list = new ArrayList<>();
            map.put("result", list);
            map.put("total", searchHits.getTotalHits());
            for (SearchHit hit : hits) {
                Map<String, Object> source = hit.getSourceAsMap();
                Map<String, Object> es     = new HashMap<>(16);
                //获取地图点的对象
                Map location = (Map) source.get("location");

                es.put("id", source.get("id"));
                es.put("nsrsbh", source.get("nsrsbh"));
                es.put("nsrmc", source.get("nsrmc"));
                es.put("lat", Double.parseDouble((String) location.get("lat")));
                es.put("lon", Double.parseDouble((String) location.get("lon")));
                list.add(es);
            }
        }
        return map;
    }

    /**
     * 转换对象，把elasticsearch返回的结果对象，转换成指定对象
     */
    private Map<String, Object> conversionDocs(SearchHits searchHits) {
        SearchHit[]         hits = searchHits.getHits();
        Map<String, Object> map  = null;
        if (hits.length > 0) {
            map = new HashMap<>();
            List<Map<String, Object>> list = new ArrayList<>();
            map.put("result", list);
            map.put("total", searchHits.getTotalHits());
            for (SearchHit hit : hits) {
                Map<String, Object> source = hit.getSourceAsMap();
                Map<String, Object> es     = new HashMap<>(16);

                es.put("id", source.get("id"));
                es.put("docNum", source.get("docNum"));
                es.put("docName", source.get("docName"));
                es.put("issuingDate", source.get("issuingDate"));
                es.put("count", source.get("count"));
                es.put("issuingAgency", source.get("issuingAgency"));
                es.put("subjectHeading", source.get("subjectHeading"));
                es.put("generatorDate", source.get("generatorDate"));
                es.put("type", source.get("type"));
                es.put("content", source.get("content"));

                Map<String, HighlightField> highlightFields = hit.getHighlightFields();

                Text[] agency = highlightFields.get("issuingAgency").fragments();
                Text[] doc    = highlightFields.get("docName").fragments();
                Text[] c      = highlightFields.get("content").fragments();
                es.put("issuingAgency2", agency[0].toString());
                es.put("docName2", doc[0].toString());
                es.put("content2", c[0].toString());

                list.add(es);
            }
        }
        return map;
    }

}
